package com.suxin;

import java.io.IOException;
import java.net.InetSocketAddress;
import java.nio.channels.SelectionKey;
import java.nio.channels.Selector;
import java.nio.channels.ServerSocketChannel;
import java.nio.channels.SocketChannel;
import java.util.Iterator;
import java.util.Set;

/**
 * @author Tang
 * @classname Reactor
 * @description [  ]
 * @date 2021/3/4 10:48
 */
public class Reactor implements Runnable {

    private final String host = "127.0.0.1";
    private final Integer port = 9000;
    private ServerSocketChannel socketChannel;
    private SelectionKey register;

    private Selector selector;

    public Reactor() {
        // 初始化server
        try {
            selector = Selector.open();
            socketChannel = ServerSocketChannel.open();
            socketChannel.configureBlocking(false);
            socketChannel.bind(new InetSocketAddress(this.host, this.port));
            register = socketChannel.register(selector, SelectionKey.OP_ACCEPT);
            // 绑定 Acceptor 处理 连接事件
            register.attach(new Acceptor());
        } catch (IOException e) {
            e.printStackTrace();
        }
    }

    @Override
    public void run() {
        while (true) {
            try {
                int select = selector.select();
                Set<SelectionKey> selectionKeys = selector.selectedKeys();
                Iterator<SelectionKey> iterator = selectionKeys.iterator();
                while (iterator.hasNext()) {
                    dispatch((SelectionKey)iterator.next());
                    iterator.remove();
                }
            } catch (IOException e) {
                e.printStackTrace();
            }
        }
    }

    private void dispatch(SelectionKey selectionKey) {
        System.out.println("interestOps--->" + selectionKey.interestOps() + "--->" + selectionKey.isReadable());
        Runnable attachment = (Runnable) selectionKey.attachment();
        if (attachment != null) {
            attachment.run();
        }
    }

    class Acceptor implements Runnable{
        @Override
        public void run() {
            try {
                SocketChannel sc = socketChannel.accept();
                // 处理业务层
                new Handler(selector, sc);
            } catch (IOException e) {
                e.printStackTrace();
            }
        }
    }
}